package com.cennavi.minemap.service;

import java.io.IOException;
import java.util.Date;

import org.apache.http.client.ClientProtocolException;
import org.geojson.LineString;
import org.geojson.LngLatAlt;
import org.geojson.Point;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cennavi.minemap.util.HttpClientUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@Service
@ComponentScan(basePackages = { "com.cennavi.minemap.util" })
@PropertySource(value = "classpath:application.properties", ignoreResourceNotFound=false)
public class BaiduService {
	@Value("${spring.service.baidu.url}")
	private String url;
	
	@Value("${spring.service.wbt.url}")
	private String wbturl;
	
	@Value("${spring.service.baidu.ak}")
	private String ak;
	
	public static ObjectMapper m_objMapper = new ObjectMapper();
	
	public String keyword(String querystr , String adCode , Integer pageNum , Integer pageCount){
		String allUrl = url + "/place/v2/search?query=" + querystr;
		
		String region = getNameByadCode(adCode);
		allUrl = allUrl + "&region=" + region;
		allUrl = allUrl + "&page_num=" + (pageNum-1);
		allUrl = allUrl + "&page_size=" + pageCount;
		allUrl = allUrl + "&scope=1&output=json";
		allUrl = allUrl + "&ak=" + ak;
		
		return dealSearchResponse(allUrl, adCode, pageNum , pageCount);
	}
	
	public String surround(String querystr , Integer pageNum , Integer pageCount , String location , Integer radius){
        String allUrl = url + "/place/v2/search?query=" + querystr;
		
		allUrl = allUrl + "&page_num=" + (pageNum-1);
		allUrl = allUrl + "&page_size=" + pageCount;
		allUrl = allUrl + "&scope=2&output=json";
		allUrl = allUrl + "&ak=" + ak;
		double lon = Double.parseDouble(location.split(",")[0]);
		double lat = Double.parseDouble(location.split(",")[1]);
		
		double[] lonlat = bd_encrypt(lon, lat);
		
		String nlocation = lonlat[0] + "," + lonlat[1];
		allUrl = allUrl + "&location=" + nlocation;
		allUrl = allUrl + "&radius=" + radius;
		allUrl = allUrl + "&coord_type=3";
		
		return dealSearchResponse(allUrl, "", pageNum, pageCount);
	}
	
	public String bbox(String querystr, Integer pageNum, Integer pageCount, String bounds) {
		String allUrl = url + "/place/v2/search?query=" + querystr;

		allUrl = allUrl + "&page_num=" + (pageNum-1);
		allUrl = allUrl + "&page_size=" + pageCount;
		allUrl = allUrl + "&scope=2&output=json";
		allUrl = allUrl + "&ak=" + ak;

		String[] bound = bounds.split(",");
		double[] lonlat1 = bd_encrypt(Double.parseDouble(bound[0]), Double.parseDouble(bound[1]));
		double[] lonlat2 = bd_encrypt(Double.parseDouble(bound[2]), Double.parseDouble(bound[3]));
		
		String nbounds = lonlat1[0] + "," + lonlat1[1] + "," + lonlat2[0] + "," + lonlat2[1];
		
		allUrl = allUrl + "&bounds=" + nbounds;
		allUrl = allUrl + "&coord_type=3";
		
		return dealSearchResponse(allUrl, "", pageNum , pageCount);
	}

	public String driving(String sPoint, String ePoint, String wayPoints, Integer costModle , Integer criteria) throws ClientProtocolException , IOException{
		
		String slon = sPoint.split(",")[0];
		String slat = sPoint.split(",")[1];
		
		String elon = ePoint.split(",")[0];
		String elat = ePoint.split(",")[1];
		
		String allUrl = url + "/direction/v1?mode=driving";
		
		allUrl = allUrl + "&origin=" + slat + "," + slon;
		allUrl = allUrl + "&destination=" + elat + "," + elon;
		
		
		if (wayPoints != null && wayPoints.trim() != null && !wayPoints.equals("")){
			String[] points = wayPoints.split(",");
		    String wayPoints_n = "";	
			for(int i = 0 ; i < points.length; i++){
				String lon = points[i];
				String lat = points[i++];
				
				wayPoints_n = wayPoints_n + "|" + lat + "," + lon;
			}
			
			wayPoints_n = wayPoints_n.substring(1);
			
			allUrl = allUrl + "&waypoints=" + wayPoints_n;
		}
		
		int tactics = 13;
		
		if (costModle == 1 || costModle == 2 || costModle == 4){
			tactics = 13;
		}else if (costModle == 16){
			tactics = 11;
		}else if (costModle == 32){
			costModle = 12;
		}else{
			tactics = 11;
		}
		
		if (criteria == 2){
			tactics = 10;
		}
		
		allUrl = allUrl + "&tactics=" + tactics;
		
		String origin_admin = getAdminName(sPoint);
		
		String destination_admin = getAdminName(ePoint);
		
		allUrl = allUrl + "&origin_region=" + origin_admin;
		allUrl = allUrl + "&destination_region=" + destination_admin;
		
		allUrl = allUrl + "&coord_type=gcj02&output=json";
		
		allUrl = allUrl + "&ak=" + ak;
		
		String response = HttpClientUtil.doGet(allUrl);
		
		JSONObject resultObj = JSONObject.parseObject(response).getJSONObject("result");
		
		JSONArray routesArr = resultObj.getJSONArray("routes");
		JSONArray rows = new JSONArray();
		for (int i = 0 ; i < routesArr.size() ; i++){
			JSONObject row = new JSONObject();
			JSONObject routeObj = routesArr.getJSONObject(i);
			
			int amount_dis = routeObj.getIntValue("distance");
			JSONObject distsum = new JSONObject();
			distsum.put("dist", amount_dis/1000.0);
			distsum.put("unit", "KM");
			row.put("distsum", distsum);
			
			int durationsum = routeObj.getIntValue("duration");
			JSONObject duration = new JSONObject();
			duration.put("duration", durationsum);
			duration.put("unit", "s");
			row.put("duration", duration);
			
			JSONObject destinationL = routeObj.getJSONObject("destinationLocation");
			double lon = destinationL.getDoubleValue("lng");
			double lat = destinationL.getDoubleValue("lat");
			JSONObject endPoint = new JSONObject();
			endPoint.put("geometry",
						JSONObject.parseObject(m_objMapper
								.writeValueAsString(new Point(new LngLatAlt(lon,
										lat)))));
			row.put("endPoint", endPoint);
			
			row.put("costModle", costModle);
			row.put("criteria", criteria);
			
			int toll = routeObj.getIntValue("toll");
			JSONObject tollObj = new JSONObject();
			tollObj.put("toll", toll);
			row.put("toll", tollObj);
			
			row.put("timestamp", new Date().getTime());
			row.put("traffic", 1);
			
			JSONArray steps = routeObj.getJSONArray("steps");
			JSONArray segmt = new JSONArray();
			row.put("segcnt", steps.size());
			for (int j = 0; j < steps.size(); j++){
				JSONObject step = steps.getJSONObject(j);
				JSONObject segment = new JSONObject();
				
				segment.put("partid", j);
				
				int dis = step.getIntValue("distance");
				JSONObject disObj = new JSONObject();
				disObj.put("dist", dis/1000.0);
				disObj.put("unit", "KM");
				segment.put("dist", disObj);
				
				String name = step.getString("instructions");
				int spos = name.indexOf("沿<b>");
				if (spos > -1) {

					String substr = name.substring(spos + "沿<b>".length());
					int epos = substr.indexOf("</b>");
					String desname = substr.substring(0, epos);
					JSONObject roadName = new JSONObject();
					roadName.put("1", desname);
					segment.put("roadName", roadName);
				}
				
				int direction = step.getIntValue("direction");
				int direct = 0;
				if (direction == 0){
					direct = 3;
				}else if (direction == 1 || direction == 2){
					direct = 2;
				}else if (direction == 3){
					direct = 1;
				}else if (direction == 4 || direction == 5){
					direct = 6;
				}else if (direction == 6){
					direct = 7;
				}else if (direction == 7 || direction == 8){
					direct = 8;
				}else if (direction == 9){
					direct = 5;
				}else if (direction == 10 || direction == 11){
					direct = 4;
				}
				segment.put("dir", direct);
				
				int turn = step.getIntValue("turn");
				int action = 0;
				if (turn == 1){
					action = 13; //直行
				}else if (turn == 2){
					action = 6; //右前转
				}else if (turn == 3){
					action = 2; //右转
				}else if (turn == 4){
					action = 8; //右后转
				}else if (turn == 5){
					action = 9;
				}else if (turn == 6){
					action = 7; //左后转
				}else if (turn == 7){
					action = 1; //左转
				}else if (turn == 8){
					action = 5; //偏左转
				}else if (turn == 9){
					action = 3; //左侧
				}else if (turn == 10){
					action = 4; //右侧
				}else if (turn == 14){
					action = 10; //环岛
				}
				
				segment.put("action", action);
				segment.put("traffic", step.getIntValue("traffic_condition"));
				
				String path = step.getString("path");
				String[] pathlist = path.split(";");
				
				segment.put("clistcnt", pathlist.length);
				String spoints = null;
				for (int k = 0; k < pathlist.length; k++){
					String mpoint = pathlist[k];
					
					double mlon = Double.parseDouble(mpoint.split(",")[0]);
					double mlat = Double.parseDouble(mpoint.split(",")[1]);
					
					double[] midpoint = bd_decrypt(mlon , mlat);
					
					if (k == 0){
						spoints = midpoint[0] + "," + midpoint[1];
					}else{
						spoints = spoints + "," + midpoint[0] + "," + midpoint[1];
					}
				}
				
				JSONObject line = decodeListCoord(spoints);
				JSONObject clist = new JSONObject();
				clist.put("geometry", line);
				segment.put("clist", clist);
				
				segmt.add(segment);
			}			
			row.put("segmt", segmt);
			rows.add(row);
		}
		JSONObject retObj = new JSONObject();
		retObj.put("error", 0);
		retObj.put("rows", rows);
		return retObj.toJSONString();
	}
	
	
	public String dealSearchResponse(String requestUrl , String adCode , int pageNum , int pageCount) {
		try {
			//requestUrl = UriEncoder.encode(requestUrl);
			String response = HttpClientUtil.doGet(requestUrl);

			JSONObject object = JSONObject.parseObject(response);
			JSONArray rows = new JSONArray();
			JSONArray results = object.getJSONArray("results");
			for (int i = 0; i < results.size(); i++) {
				JSONObject result = results.getJSONObject(i);
				JSONObject row = new JSONObject();

				int detail = result.getIntValue("detail");
				if (detail == 1) {
					JSONObject detail_info = result.getJSONObject("detail_info");
					if (detail_info != null) {

						if (detail_info.containsKey("distance")) {
							int distance = detail_info.getIntValue("distance");
							row.put("distance", distance);
						}
					}
				}
				
				String name = result.getString("name");
				row.put("name", name);
				
				String address = result.getString("address");
				row.put("address", address);
				
				String id = result.getString("uid");
				row.put("id", id);
				
				double lon = result.getJSONObject("location").getDoubleValue("lng");
				double lat = result.getJSONObject("location").getDoubleValue("lat");
				
				double[] lonlat = bd_decrypt(lon, lat);
				
				JSONObject geom = new JSONObject();
				geom.put("geometry",
							JSONObject.parseObject(m_objMapper
									.writeValueAsString(new Point(new LngLatAlt(lonlat[0],
											lonlat[1])))));
				
				row.put("geom", geom);
				
				JSONObject geom_display = new JSONObject();
				geom_display.put("geometry",
							JSONObject.parseObject(m_objMapper
									.writeValueAsString(new Point(new LngLatAlt(lonlat[0],
											lonlat[1])))));
				
				row.put("geom_display", geom_display);
				
				if (result.containsKey("telephone")){
					row.put("tel", result.getString("telephone"));
				}
				
				row.put("adcode", adCode);
				
				rows.add(row);
			}
			
			JSONObject retObj = new JSONObject();
			retObj.put("rows", rows);
			retObj.put("total", object.getIntValue("total"));
			retObj.put("pageNumber", pageNum);
			retObj.put("pageCount", pageCount);
			
			return retObj.toJSONString();

		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}
	
	public String getAdminName(String point){
		
		String adurl = "http://minedata.cn/service/search/adminByPoint?token=sjfidjsfijsf";
		adurl = url + "&location=" + point;
		try {
			String response = HttpClientUtil.doGet(adurl);
			
			JSONObject object = JSONObject.parseObject(response).getJSONObject("data");
			
			String province = object.getString("province");
			String city = object.getString("city");
			
			if (province == null || province.length() == 0){
				city = city.replace("辖区","");
				return city;
			}else{
				province = province.replace("辖区", "");
				return province;
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	public String getNameByadCode(String adCode){
		if (adCode == null || adCode.trim() == null || adCode.equals("")){
			return "全国";
		}
		
		String webturl = wbturl + "token=isdfiasdgjig" + "/gis/metadataquery/adcode.json?adcode=" + adCode;
        webturl = webturl + "&recursion=1";
        
        try{
        	String response = HttpClientUtil.doGet(webturl);
        	
        	JSONObject object = JSONObject.parseObject(response).getJSONObject("response");
        	
            JSONObject result = object.getJSONObject("result");
            JSONArray arr = result.getJSONArray("adcodelist");
            
            if (arr.size() > 0){
            	JSONObject adObj = arr.getJSONObject(0);
            	
            	String name = adObj.getString("name");
            	name = name.replace("辖区", "");
            	return name;
            }
        }catch(IOException e){
        	e.printStackTrace();
        }
		return "全国";
	}
    /**
     * 百度坐标解密(百度坐标转火星坐标)
     *
     * @param bd_lon 百度坐标经度
     * @param bd_lat 百度坐标纬度
     * @return 经纬度
     */
    public double[] bd_decrypt(double bd_lon, double bd_lat) {
    	double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        double gg_lat;
        double gg_lon;
        double x = bd_lon - 0.0065, y = bd_lat - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        gg_lon = z * Math.cos(theta);
        gg_lat = z * Math.sin(theta);
        double a[] = {gg_lon, gg_lat};
        return a;
    }
    
    /**
     * 百度坐标加密(火星坐标转百度坐标)
     *
     * @param gg_lon 经度
     * @param gg_lat 纬度
     * @return 百度坐标经纬度
     */
    public static double[] bd_encrypt(double gg_lon, double gg_lat) {
    	double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        double bd_lat;
        double bd_lon;
        double x = gg_lon, y = gg_lat;
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
        bd_lon = z * Math.cos(theta) + 0.0065;
        bd_lat = z * Math.sin(theta) + 0.006;
        double a[] = {bd_lat, bd_lon};
        return a;
    }
    
	public static JSONObject decodeListCoord(String input) {
		LineString line = new LineString();
		String[] coordArray = input.split(",");

		for (int i = 0; i < coordArray.length - 1; i += 2) {
			line.add(new LngLatAlt(Double.parseDouble(coordArray[i]), Double.parseDouble(coordArray[i + 1])));
		}

		String rString = "";

		try {
			rString = m_objMapper.writeValueAsString(line);
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return JSONObject.parseObject(rString);
	}
}
